Xcode 16.0とiOS 18.0シミュレータの組み合わせでSafariViewControllerがフリーズしてしまう不具合を解消する
Xcode 16.0とiOS 18.0シミュレータの組み合わせで、SFSafariViewController
が表示されない不具合を発見した。
Xcode 16.0でビルドしたアプリでデバッグ実行し、SFSafariViewController
を表示させようとした時に真っ白い画面になったり、閉じるボタンがステータスバーの裏側に入りこみ、アプリがフリーズしてしまう現象である。私はiOS 18.0シミュレータの不具合と考えているが、2024年9月27日時点では解消する目処が立っていない。
この問題の理由については明確ではないが、Xcodeのプロジェクト設定を調整することで正常に表示できるようになったため、不具合の原因と今後の対応について共有したい。
不具合の原因
Excluded Architectures
のAny iOS Simulator SDK
にarm64
を設定していると、iOS 18.0シミュレータのSFSafariViewController
で正常に動作しなくなってしまう。この設定は以下のスクリーンショットの場所にある。
project.pbxproj
上では、以下のように表現されていることがある。また、Podfile
で定義されている場合もある。
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
Appleシリコンを搭載したMacでは、シミュレーターがarm64
アーキテクチャを使用している。IntelベースのMacではx86_64
アーキテクチャを使用するため、この設定でarm64
を除外することでシミュレーターが動作するようにしている。Intel MacからAppleシリコン Macへの移行時によく設定されていたかと思う。
不具合の発生するミニマムコード
問題が発生する最小構成のコードを以下に示す。ボタンをタップするとSafariViewController
をラップしたSafariView
を表示するだけの簡単なコードである。
import SafariServices
import SwiftUI
struct SafariView: UIViewControllerRepresentable {
let url = URL(string: "https://dev.classmethod.jp/")!
func makeUIViewController(context _: Context) -> SFSafariViewController {
let controller = SFSafariViewController(url: url)
controller.dismissButtonStyle = .close
controller.preferredControlTintColor = .green
return controller
}
func updateUIViewController(_: SFSafariViewController, context _: Context) {}
}
struct ContentView: View {
@State private var showSafariView = false
var body: some View {
VStack {
Button(action: { showSafariView = true }) {
Text("Open SafariView")
}
}
.fullScreenCover(isPresented: $showSafariView) {
SafariView()
}
}
}
#Preview {
ContentView()
}
このコードをiOS 18シミュレータで実行したとき、EXCLUDED_ARCHS
の設定によって挙動が異なる。EXCLUDED_ARCHS
でarm64
を設定している場合、SFSafariViewController
が真っ白く表示されたり、不正な表示になってしまう。
EXCLUDED_ARCHSでarm64が設定されている | EXCLUDED_ARCHSの設定をしていない |
---|---|
まとめ
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
を削除することで、Xcode 16.0とiOS 18.0シミュレータの組み合わせにおいても、SFSafariViewController
を正常に動作させることができた。この問題はAppleによる不具合の可能性が高いと考えている。
今年の6月の時点でAppleデベロッパーフォーラムにて報告があったが、その時点では原因が特定されておらず、Appleのエンジニアも不具合の原因を特定できなかったのだろう。修正されずに iOS 18.0 Releaseがリリースされてしまったようだ。
解決策と今後の対応
サードパーティSDKの arm64 対応が進み、多くのアプリにおいては、"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
を削除しても正常に動作するケースが多いと思う。
ただし、特定のサードパーティSDKに依存している場合、簡単には解決しないかもしれない。以下の図のように、ライブラリがarm64
を含むかどうかを確認する必要がある。上のライブラリでは、xcframeworkに ios-arm64_x86_64-simulator
が含まれており、arm64に対応しており問題がないことがわかる。
しかし、下のライブラリはios-x86_64-simulator
となっており、arm64に対応していないことがわかる。このような事例の場合は、SDKの提供元に修正を依頼する必要がある。
この不具合に関しては、昔からメンテナンスを続けてきたいわゆる「老舗」のアプリほど影響を受けるだろう。影響を受けるアプリも多いことが想定されるため、Appleの迅速な修正を期待しても良いかもしれない。iOS 18.0の実機やiOS 17.xシミュレータでは正常に動作するため、解決までの間は最小限の不便さで済むだろう。
関連するApple Developerフォーラムの課題は以下の通りだ。問題が解決するまでウォッチしたいと思う。
(2024/10/09追記) UIImagePickerControllerでも同様にフリーズする
本記事の中ではSFSafariViewController
のことのみ記載したが、UIImagePickerController
でも同様のフリーズする現象が発生することがわかった。React NativeとFlutterでも本事象についてのIssueが投稿されていた。
- [🐛] The image library picker freezes on iOS 18
- Image picker freezes on ios 18 simulator. (maybe on real device as well)
(2024/10/25追記) Xcode 16.1 RCでも修正されていない
先日、Xcode 16.1 Release Candidate と iOS 18.1 RCシミュレータが配信された。Xcode 16.1とiOS 18.1 RCシミュレータの組み合わせで調査したが問題は継続して発生していた。Appleとしてはこの現象について認識していると考えているが現時点では修正されていない。
2020年にAppleシリコンが登場してから4年が経過しており、Appleからするとx86_x64対応を残すメリットがないので、この問題の優先度が低いのかもしれない。
私が開発しているアプリでは、特定のサードパーティSDKに依存しているため、SDKの提供元にarm64対応を強くリクエストをしていきたいと考えている。